package ar.uba.fi.RSACryptoFiuba.model;

import java.math.BigInteger;
import java.util.Random;

import org.apache.commons.math3.primes.Primes;
import org.apache.commons.math3.util.ArithmeticUtils;

public class RSACalculator {
	
	public static Integer add(Integer a, Integer b){
		return a + b;
	}
	
	public static Integer extract(Integer a, Integer b){
		return a - b;
	}
	
	public static Integer divide(Integer a, Integer b){
		return a / b;
	}
	
	public static Integer getRandomPrime(){
		Random rand = new Random();
        int randomNumber = rand.nextInt(100) + 1;
        Integer primeNumber = Primes.nextPrime(randomNumber);
		return primeNumber;
	}
	
	public static Integer getRandomPrimeDifferentFrom(Integer anotherPrime){
		Integer primeNumber = getRandomPrime();
		while(primeNumber.equals(anotherPrime)){	
			primeNumber = RSACalculator.getRandomPrime();
		}
		return primeNumber;
	}
	
	public static Integer multiply(Integer a, Integer b){
		return a * b;
	}
	
	public static Integer getCoprime(Integer prime){
		Random rand = new Random();
		Integer coprime = rand.nextInt(100) + 1;
		while(ArithmeticUtils.gcd(prime, coprime)!=1){
			coprime = rand.nextInt(100) + 1;
		}
		return coprime;
	}
	
	public static Integer getModMultiplicativeInverse(Integer n, Integer mod){
		BigInteger nBigInt = new BigInteger(n.toString());
        BigInteger modBigInt = new BigInteger(mod.toString());
        BigInteger multiplicativeInverse = nBigInt.modInverse(modBigInt);
        return multiplicativeInverse.intValue();
	}

	public static String getASCIIRepresentation(String text) {
		String asciiText = "";
		int amountOfDigits = 3;
		for (int i = 0; i < text.length(); i++) {
			String asciiRepresentation = getASCIIvalue(text.charAt(i), amountOfDigits);
			asciiText = asciiText.concat(asciiRepresentation);
		}
		return asciiText;
	}
	
	public static String getASCIIvalue(char character, Integer amountOfDigits) {
		int asciiValue = (int) character;
		String asciiRepresentation = String.valueOf(asciiValue);
		String leftPaddedString = String.format("%"+amountOfDigits+"s", asciiRepresentation).replace(' ', '0');
		return leftPaddedString;
	}
	
	public static String getTextFromASCII(String asciiRepresentation) {
		String text = "";
		int amountOfDigits = 3;
		while(asciiRepresentation.length() >= amountOfDigits){
			String ascii = asciiRepresentation.substring(0, 3);
			asciiRepresentation = asciiRepresentation.substring(3);
			text+= getCharFromASCII(ascii);
		}
		return text;
	}
	
	private static char getCharFromASCII(String ascii) {
		int intAscii = Integer.parseInt(ascii);
		return (char)intAscii;
	}

	public static BigInteger exp(BigInteger a, Integer b) {
        return a.pow(b);
	}

	public static BigInteger mod(BigInteger a, BigInteger modulus) {
		return a.mod(modulus);
	}

	public static boolean isPrime(Integer a) {
		return Primes.isPrime(a);		
	}

	public static boolean areCoprime(Integer a, Integer b) {
		return ArithmeticUtils.gcd(a, b) == 1;
	}

}
